Step 32: Validation with Zod

Let’s look at the Bookmark schema again:

import mongoose from "mongoose";

const BookmarkSchema = new mongoose.Schema({
  title: { type: String, required: [true, "Each bookmark must have a title"] },
  url: { type: String, required: [true, "Each bookmark must have a URL"] },
});

const Bookmark = mongoose.model("Bookmark", BookmarkSchema);

export default Bookmark;

Think about the URL attribute. Is it enough for it to be a nonempty string? You probably want to make sure the URL is valid. Mongoose does not have a function to validate a URL. However, it allows you to write your own.

We will not write our own URL validation. Instead, we will use. validation library that had this and many other validation methods.

Add Zod as a dependency:

yarn add zod

Update the src/model/Bookmark.js file as follows:

import mongoose from "mongoose";
import { z } from "zod";

const BookmarkSchema = new mongoose.Schema({
  title: { type: String, required: [true, "Each bookmark must have a title"] },
  url: { type: String, required: [true, "Each bookmark must have a URL"] },
});

BookmarkSchema.path("url").validate((url) => {
  try {
    z.string().url().parse(url);
    return true;
  } catch (err) {
    return false;
  }
}, "Invalid URL");

const Bookmark = mongoose.model("Bookmark", BookmarkSchema);

export default Bookmark;

Add the following test to tests/model/Bookmark.test.js:

it("test url is invalid", async () => {
  try {
    const title = faker.lorem.sentence();
    const url = faker.lorem.sentence();
    await Bookmark.create({ title, url });
  } catch (err) {
    expect(err).toBeDefined();
  }
});

Save and commit the changes.